练习
(1)编写代码,定义一个基类 MyClass
,其中包含虚拟方法 GetString()
。这个方法应返回存储在受保护字段 myString
中的字符串,该字段可以通过只写公共属性 ContainedString
来访问。
答案:
class MyClass { protected string myString; public string ContainedString { set { myString = value; } } public virtual string GetString() { return myString; } }
(2)从类 MyClass
中派生一个类 MyDerivedClass
。重写 GetString()
方法,使用该方法的基类实现代码从基类中返回一个字符串,但在返回的字符串中添加文本 “(output from derived class)”。
答案:
class MyDerivedClass : MyClass { public override string GetString() { return base.GetString() + " (output from derived class)"; } }
(3)部分方法定义必须使用 void
返回类型。说明其原因。
答案: 如果方法具有返回类型,就可以将其用作表达式的一部分:
x = Manipulate(y, z);
如果没有给部分方法提供实现代码,编译器就会在使用该部分方法的所有地方删除该方法。在上面的代码中,这会使x的结果变得模糊,因为Manipulate()方法没有替代方法。如果没有这个方法,可能只需忽略整行代码,但编译器无法确定我们是否的确希望忽略它。
没有返回类型的方法不能作为表达式的一部分来调用,所以编译器可以安全地删除对部分方法调用的所有引用。
同样,也禁止使用out参数,因为在方法调用之前,用作out参数的变量必须是未定义的,而应在方法调用之后定义。而应在方法调用之后定义。删除方法定义会违反这个规则。
(4)编写一个类 MyCopyableClass
,该类可以使用方法 GetCopy()
返回它本身的一个副本。这个方法应使用派生于 System.Object 的 MemberwiseClone()
方法。给该类添加一个简单的属性,并且编写客户代码,客户代码使用该类检查任务是否成功执行。
答案:
class MyCopyableClass { protected int myInt; public int ContainedInt { get { return myInt; } set { myInt = value; } } public MyCopyableClass GetCopy() { return (MyCopyableClass)MemberwiseClone(); } }
客户端代码:
class Program { static void Main(string[] args) { MyCopyableClass obj1 = new MyCopyableClass(); obj1.ContainInt = 5; MyCopyableClass obj2 = obj1.GetCopy(); obj1.ContainedInt = 9; Console.WriteLine(obj2.ContainedInt); } }
这些代码显示5,说明所复制对象有自己专用的myInt字段。
(5)为 Ch10CardLib
库编写一个控制台客户程序,从洗牌后的 Deck
对象中一次取出 5 张牌。如果这 5 张牌都是相同花色,客户程序就应在屏幕上显示这 5 张牌,以及文本 "Flush!",否则在取出 50 张牌以后就输出文本 “No flush”,并退出。
答案:
using System; using Ch10CardLib; namespace Exercise_Answers { class Class1 { static void Main(string[] args) { while(true) { Deck playDeck = new Deck(); playDeck.Shuffle(); bool isFlush = false; int flushHandIndex = 0; for(int hand = 0; hand < 10; hand++) { ifFlush = true; Suit flushSuit = playDeck.GetCard(hand * 5).suit; for(int card = 1; card < 5; card++) { if(playDeck.GetCard(hand * 5 + card).suit != flushSuit) { isFlush = false; } } if(isFlush) { flushHandIndex = hand * 5; break; } } if(isFlush) { Console.WriteLine("Flush!"); for(int card = 0; card < 5; card++) { Console.WriteLine(playDeck.GetCard(flushHandIndex + card)); } } else { Console.WriteLine("No flush."); } Console.ReadLine(); }// end while }// end Main } }
这些代码会循环下去,因为同花色是不常见的。可能需要按几次回车键,才能在洗好的扑克牌中找到一个同花色。为了验证一切如期执行,可以尝试将洗牌的代码行注释掉。
🔚